哈罗面试:没开sql慢查询日志,怎么发现慢 sql?

一:什么是 慢 SQL(慢查询) 日志?

MySQL的慢查询日志是MySQL提供的一种日志记录。

MySQL的慢查询日志 ,主要 用来记录在MySQL中响应的时间超过 执行时长阈值的语句, 执行时长阈值 通过 一个 参数 long_query_time(默认是10秒)配置。

一个SQL的执行,只要 超过 这个 long_query_time 时长, 就会被判为慢查询, 会被记录到慢查询日志中。

二: SQL 到底 执行 多长时间,才为慢SQL ?

慢 SQL 时间 长度是   “执行耗时超出业务或数据库的合理阈值”,但具体定义需结合数据库类型、业务场景、硬件配置综合判断,无绝对统一标准。

慢 SQL 时间 长度 通常分为 通用阈值 和 业务定制阈值 两类:

第一个维度:通用参考阈值(以 MySQL 为例)

数据库层面默认有基础标准,最典型的是 MySQL 的long_query_time参数(慢查询日志的核心触发条件):

默认值: 10 秒 (即执行时间≥10 秒的 SQL 会被标记为慢 SQL);

实际场景: 多数业务会将阈值下调至1-2 秒(因 10 秒远超用户可接受的响应时间,比如 Web 页面加载通常要求 < 2 秒,接口响应 < 500ms)。

第二个维度:业务定制阈值(更关键)

通用阈值仅作参考,真正的慢 SQL 定义需贴合业务场景,例如:

三:如何设置 慢SQL 相关参数?

下面是一些关键参数设置:

设置成 1,日志就开启;设置成 0,日志就关闭。

这两个参数用来指定慢查询日志的保存位置。如果不设置,系统会自动生成一个默认文件,名字是 “主机名 - slow.log”。

它决定了什么样的查询算慢查询,只要 SQL 语句执行时间超过这里设置的时长,就会被记录到日志里。

这是个可选参数,打开后,没命中索引的查询语句也会被记录下来。

有 FILE(快) , TABLE(满) 两种方式保持日志。设置成FILE,日志就存到文件里,这是默认方式;

设置成  TABLE,日志会存到数据库的mysql.slow_log表里。

也可以同时用两种方式,写成FILE,TABLE。不过,存到数据库表比存到文件更费资源,如果既想开慢查询日志,又想数据库跑得快,建议优先把日志存到文件里。

slow_query_log 的 参数查看:

  
mysql> show VARIABLES like '%slow_query_log%';  
+---------------------+-----------------------------------------------------------+  
| Variable_name       | Value                                                     |  
+---------------------+-----------------------------------------------------------+  
| slow_query_log      | OFF                                                       |  
| slow_query_log_file | d:\java\mysql-5.7.28-winx64\data\DEEP-2020AEBKQR-slow.log |  
+---------------------+-----------------------------------------------------------+  
2 rows in set, 1 warning (0.00 sec)  
  

long_query_time 的 参数查看:

mysql> show VARIABLES like 'long_query_time%';  
+-----------------+-----------+  
| Variable_name   | Value     |  
+-----------------+-----------+  
| long_query_time | 10.000000 |  
+-----------------+-----------+  
1 row in set, 1 warning (0.00 sec)  

设置启用慢查询日志:

  
SET GLOBAL slow_query_log = 'ON';  
SET GLOBAL long_query_time = 1;  

注意:修改全局参数后,当前连接会话仍使用旧值,需新建会话才会生效,需要重新登录

查看修改后参数:

  
mysql> show VARIABLES like '%slow_query_log%';  
+---------------------+-----------------------------------------------------------+  
| Variable_name       | Value                                                     |  
+---------------------+-----------------------------------------------------------+  
| slow_query_log      | ON                                                        |  
| slow_query_log_file | d:\java\mysql-5.7.28-winx64\data\DEEP-2020AEBKQR-slow.log |  
+---------------------+-----------------------------------------------------------+  
2 rows in set, 1 warning (0.00 sec)  
mysql> show VARIABLES like 'long_query_time%';  
+-----------------+----------+  
| Variable_name   | Value    |  
+-----------------+----------+  
| long_query_time | 1.000000 |  
+-----------------+----------+  
1 row in set, 1 warning (0.00 sec)  
  

四:3大 慢 SQL 分析工具

慢查询分析一般分为三个步骤

1、 EXPLAIN2、 OPTIMIZER_TRACE3、 PROFILE
上面三大工具的 具体使用方法,请参见尼恩之前的博客文章:

凌晨2点,报警群炸了:一条sql 执行200秒!搞定之后,我总结了一个慢SQL查询、定位分析解决的完整套路

五、没开慢查询日志,怎么发现慢 SQL? (4个方法)

慢查询日志是 “事后追溯” 的核心工具,但未开启时,可通过「实时监控」「资源排查」「业务反馈」三类手段主动发现慢 SQL,覆盖实时问题定位历史问题追溯场景。

5.1 抓现行: 实时监控面板

首先借助 直观的实时监控, 借助可视化工具 ,监控慢sql:

5.2  抓现行: 实时 DB 定位

适用于 “业务反馈卡顿”“数据库 CPU/IO 飙升” 等紧急场景,直接查看数据库当前运行的 SQL,定位耗时久的语句。

用到命令:

这是最常用的实时排查命令,能查看当前所有数据库连接的执行状态、耗时、SQL 内容。

关键字段解读(重点关注 3 个字段):

字段名 含义
Time SQL 已执行的时间(单位:秒),若远超阈值(如 > 3 秒),大概率是慢 SQL
State SQL 当前的执行状态,如Sending data(数据传输,耗时可能长)、Locked(锁等待)
Info 完整的 SQL 语句(若过长,需用show full processlist;查看完整内容)

示例

若发现Time=15(执行了 15 秒)、State=Sending dataInfo=select * from order where create_time < '2024-01-01',则该 SQL 是典型的慢 SQL。

5.3.  日志与链路追踪:从 “业务卡顿” 定位 SQL

业务层的异常反馈是慢 SQL 的重要线索,通过业务日志和链路追踪工具可反向找到对应的 SQL:

  1. 步骤 1:收集业务反馈(如 “用户提交订单时卡顿了 5 秒”),确定异常时间(如 2024-05-20 14:30)和业务接口(如/order/submit);
  2. 步骤 2:查看应用日志(如 Java 的 Logback、Python 的 logging),找到该接口对应的 SQL 执行记录(若应用打印了 SQL 耗时,直接定位);
  3. 步骤 3:若应用未打印 SQL,用链路追踪工具(如 SkyWalking )查看接口调用链,找到 “数据库调用” 节点,查看耗时(如 “MySQL 调用耗时 4.5 秒”),并提取对应的 SQL 语句。

5.4 历史追溯: 查历史执行记录 发现 慢 SQL

若慢 SQL 已执行完毕(如夜间批量任务),可以 通过 “资源使用记录”“业务日志” 间接追溯。

5.4 .1.  分析 历史执行记录表中 的 “执行统计信息”

部分数据库会留存近期的 SQL 执行统计信息,可通过系统表查询:

#(默认保留 1000 条历史 SQL,可通过setup\_consumers调整保留数):
performance_schema.events_statements_history  
-- 筛选执行时间>3秒的历史SQL(单位:微秒,需转换为秒)  
select sql_text, timer_wait/1000000000 as exec_time   
from performance_schema.events_statements_history   
where timer_wait/1000000000 > 3   
order by exec_time desc;  

5.4 .2. 分析  历史执行记录  “全表扫描SQL ”

还可主动扫描数据库中 “可能成为慢 SQL” 的语句(如无索引、全表扫描的 SQL)。

比如,全表扫描(type=ALL)是慢 SQL 的主要诱因,可通过explain分析 SQL 执行计划,或直接查询系统表筛选:

-- 筛选出全表扫描且行数>1万的SQL(潜在慢SQL)  
select sql_text, rows_examined   
from performance_schema.events_statements_history   
where rows_examined > 10000   
  and (sql_text like 'select%' or sql_text like 'update%' or sql_text like 'delete%')  
order by rows_examined desc;  

其中: